﻿using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

/*using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Diagnostics;*/



namespace DienLib
{
    public enum BlinkSpeed { BLINK_SLOW = 500, BLINK_NORMAL = 250, BLINK_FAST = 100, BLINK_VERYFAST = 50 }
    public enum FindCulture { EXACT_MATCH, EXACT_MATCH_IGNORE_CASE, PARTIAL_MATCH, PARTIAL_MATCH_IGNORE_CASE };
    public partial class WinAPI
    {
        #region CONFIG_VARIABLE
        /// <summary>
        /// Set this for BlinkBorderBefore & BlinkBorderAfter()
        /// Use the SetBlinkSpeed() & GetBlinkSpeed() Instead
        /// </summary>
        private static BlinkSpeed BLINK_SPEED = BlinkSpeed.BLINK_NORMAL;
        #endregion

        #region CTYPE Definition
        #region FOR MOUSE_EVENT
        [Flags]
        public enum MouseEventFlags : uint
        {
            LEFTDOWN = 0x00000002,
            LEFTUP = 0x00000004,
            MIDDLEDOWN = 0x00000020,
            MIDDLEUP = 0x00000040,
            MOVE = 0x00000001,
            ABSOLUTE = 0x00008000,
            RIGHTDOWN = 0x00000008,
            RIGHTUP = 0x00000010,
            WHEEL = 0x00000800,
            XDOWN = 0x00000080,
            XUP = 0x00000100
        }

        //Use the values of this enum for the 'dwData' parameter
        //to specify an X button when using MouseEventFlags.XDOWN or
        //MouseEventFlags.XUP for the dwFlags parameter.
        public enum MouseEventDataXButtons : uint
        {
            XBUTTON1 = 0x00000001,
            XBUTTON2 = 0x00000002
        }
        #endregion

        public enum PenStyle
        {
            PS_SOLID = 0,
            PS_DASH = 1,   /* -------  */
            PS_DOT = 2,     /* .......  */
            PS_DASHDOT = 3,     /* _._._._  */
            PS_DASHDOTDOT = 4,     /* _.._.._  */
            PS_NULL = 5,
            PS_INSIDEFRAME = 6,
            PS_USERSTYLE = 7,
            PS_ALTERNATE = 8,
        }

        /// <summary>
        ///     Specifies a raster-operation code. These codes define how the color data for the
        ///     source rectangle is to be combined with the color data for the destination
        ///     rectangle to achieve the final color.
        /// </summary>
        enum TernaryRasterOperations : uint
        {
            /// <summary>dest = source</summary>
            SRCCOPY = 0x00CC0020,
            /// <summary>dest = source OR dest</summary>
            SRCPAINT = 0x00EE0086,
            /// <summary>dest = source AND dest</summary>
            SRCAND = 0x008800C6,
            /// <summary>dest = source XOR dest</summary>
            SRCINVERT = 0x00660046,
            /// <summary>dest = source AND (NOT dest)</summary>
            SRCERASE = 0x00440328,
            /// <summary>dest = (NOT source)</summary>
            NOTSRCCOPY = 0x00330008,
            /// <summary>dest = (NOT src) AND (NOT dest)</summary>
            NOTSRCERASE = 0x001100A6,
            /// <summary>dest = (source AND pattern)</summary>
            MERGECOPY = 0x00C000CA,
            /// <summary>dest = (NOT source) OR dest</summary>
            MERGEPAINT = 0x00BB0226,
            /// <summary>dest = pattern</summary>
            PATCOPY = 0x00F00021,
            /// <summary>dest = DPSnoo</summary>
            PATPAINT = 0x00FB0A09,
            /// <summary>dest = pattern XOR dest</summary>
            PATINVERT = 0x005A0049,
            /// <summary>dest = (NOT dest)</summary>
            DSTINVERT = 0x00550009,
            /// <summary>dest = BLACK</summary>
            BLACKNESS = 0x00000042,
            /// <summary>dest = WHITE</summary>
            WHITENESS = 0x00FF0062,
            /// <summary>
            /// Capture window as seen on screen.  This includes layered windows 
            /// such as WPF windows with AllowsTransparency="true"
            /// </summary>
            CAPTUREBLT = 0x40000000
        }

        const int DSTINVERT = 0x00550009;
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            private int _Left;
            private int _Top;
            private int _Right;
            private int _Bottom;

            public RECT(RECT Rectangle)
                : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom)
            {
            }
            public RECT(int Left, int Top, int Right, int Bottom)
            {
                _Left = Left;
                _Top = Top;
                _Right = Right;
                _Bottom = Bottom;
            }

            public int X
            {
                get { return _Left; }
                set { _Left = value; }
            }
            public int Y
            {
                get { return _Top; }
                set { _Top = value; }
            }
            public int Left
            {
                get { return _Left; }
                set { _Left = value; }
            }
            public int Top
            {
                get { return _Top; }
                set { _Top = value; }
            }
            public int Right
            {
                get { return _Right; }
                set { _Right = value; }
            }
            public int Bottom
            {
                get { return _Bottom; }
                set { _Bottom = value; }
            }
            public int Height
            {
                get { return _Bottom - _Top; }
                set { _Bottom = value + _Top; }
            }
            public int Width
            {
                get { return _Right - _Left; }
                set { _Right = value + _Left; }
            }
            public Point Location
            {
                get { return new Point(Left, Top); }
                set
                {
                    _Left = value.X;
                    _Top = value.Y;
                }
            }
            public Size Size
            {
                get { return new Size(Width, Height); }
                set
                {
                    _Right = value.Width + _Left;
                    _Bottom = value.Height + _Top;
                }
            }

            public static implicit operator Rectangle(RECT Rectangle)
            {
                return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height);
            }
            public static implicit operator RECT(Rectangle Rectangle)
            {
                return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom);
            }
            public static bool operator ==(RECT Rectangle1, RECT Rectangle2)
            {
                return Rectangle1.Equals(Rectangle2);
            }
            public static bool operator !=(RECT Rectangle1, RECT Rectangle2)
            {
                return !Rectangle1.Equals(Rectangle2);
            }

            public override string ToString()
            {
                return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}";
            }

            public override int GetHashCode()
            {
                return ToString().GetHashCode();
            }

            public bool Equals(RECT Rectangle)
            {
                return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom;
            }

            public override bool Equals(object Object)
            {
                if (Object is RECT)
                {
                    return Equals((RECT)Object);
                }
                else if (Object is Rectangle)
                {
                    return Equals(new RECT((Rectangle)Object));
                }

                return false;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;

            public POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }

            public static implicit operator System.Drawing.Point(POINT p)
            {
                return new System.Drawing.Point(p.X, p.Y);
            }

            public static implicit operator POINT(System.Drawing.Point p)
            {
                return new POINT(p.X, p.Y);
            }
        }

        #endregion

        #region Win32API Definition
        [DllImport("user32.dll")]
        public static extern uint MapVirtualKey(uint uCode, uint uMapType);

        [DllImport("user32.dll", SetLastError = true)]
        internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

        [DllImport("user32.dll")]
        public static extern int ShowWindow(int hwnd, int nCmdShow);

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, string lParam);
        [DllImport("user32.dll")]
        public static extern uint SendMessage(IntPtr hWnd, uint MSG, uint zero, byte[] text);
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        [DllImport("user32.dll")]
        public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        [DllImport("user32.dll")]
        public static extern int GetParent(int hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        [DllImport("User32.Dll")]
        public static extern void GetWindowText(IntPtr hWnd, StringBuilder winTitle, int nMaxCount);

        [DllImport("User32.Dll")]
        public static extern void GetClassName(IntPtr hWnd, StringBuilder winClass, int nMaxCount);

        [DllImport("USER32.DLL")]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("User32.dll")]
        public static extern IntPtr SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern IntPtr GetWindowDC(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        /// <summary>
        /// The ClientToScreen API converts the client-area coordinates of a specified point to screen coordinates.
        /// </summary>
        /// <param name="hWnd">Handle of Client Window</param>
        /// <param name="lpPoint">Point output to Screen Coord</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);

        [DllImport("user32.dll")]
        static extern IntPtr WindowFromPoint(Point p);

        [DllImport("user32.dll")]
        static extern void GetWindowRect(IntPtr hWnd, Rectangle rect);

        [DllImport("user32.dll")]
        static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("User32.dll")]
        static extern void ReleaseDC(IntPtr hDC);

        [DllImport("gdi32.dll")]
        static extern int SetROP2(IntPtr hDC, int fnDrawMode);

        [DllImport("gdi32.dll")]
        static extern IntPtr CreatePen(PenStyle fnPenStyle, int nWidth, uint crColor);

        [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool Polyline(IntPtr hdc, [In] POINT[] lppt, int cPoints);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);

        /// <summary>
        ///    Performs a bit-block transfer of the color data corresponding to a
        ///    rectangle of pixels from the specified source device context into
        ///    a destination device context.
        /// </summary>
        /// <param name="hdc">Handle to the destination device context.</param>
        /// <param name="nXDest">The leftmost x-coordinate of the destination rectangle (in pixels).</param>
        /// <param name="nYDest">The topmost y-coordinate of the destination rectangle (in pixels).</param>
        /// <param name="nWidth">The width of the source and destination rectangles (in pixels).</param>
        /// <param name="nHeight">The height of the source and the destination rectangles (in pixels).</param>
        /// <param name="hdcSrc">Handle to the source device context.</param>
        /// <param name="nXSrc">The leftmost x-coordinate of the source rectangle (in pixels).</param>
        /// <param name="nYSrc">The topmost y-coordinate of the source rectangle (in pixels).</param>
        /// <param name="dwRop">A raster-operation code.</param>
        /// <returns>
        ///    <c>true</c> if the operation succeeded, <c>false</c> otherwise.
        /// </returns>
        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);

        [DllImport("Shell32.dll")]
        static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);

        [DllImport("user32.dll")]
        static extern bool OffsetRect(ref RECT lprc, int dx, int dy);

        [DllImport("gdi32.dll")]
        static extern bool PatBlt(IntPtr hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, uint dwRop);

        public delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true)]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);

        [DllImport("user32.dll")]
        static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);

        [DllImport("user32.dll")]
        static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);

        #endregion

        #region Extra Wrapper Function

        public static void MouseLeftClick(int x, int y)
        {
            Cursor.Position = new System.Drawing.Point(x, y);
            mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
            mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
        }

        public static void MouseDoubleClick(int x, int y)
        {
            Cursor.Position = new System.Drawing.Point(x, y);
            mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
            mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
            System.Threading.Thread.Sleep(200); // Simulate Physical Delay between 2 Click
            mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
            mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
        }

        public static void MouseRightClick(int x, int y)
        {
            Cursor.Position = new System.Drawing.Point(x, y);
            mouse_event((int)(MouseEventFlags.RIGHTDOWN), 0, 0, 0, 0);
            mouse_event((int)(MouseEventFlags.RIGHTUP), 0, 0, 0, 0);
        }

        /// <summary>
        /// Send Key to current Focus Windows
        /// </summary>
        /// <param name="key">Key to send</param>
        /// <param name="up">TRUE : Key Up & FALSE : Key Down</param>
        public static void PressKey(Keys key, bool up)
        {
            const int KEYEVENTF_EXTENDEDKEY = 0x1;
            const int KEYEVENTF_KEYUP = 0x2;
            if (up)
            {
                keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);
            }
            else
            {
                keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);
            }
        }

        /// <summary>
        /// Send Key to Window specify by Handle
        /// </summary>
        /// <param name="window">Window Handle</param>
        /// <param name="key">Key to send</param>
        /// <param name="up">True : Key Up or False : Key Down</param>
        public static void PressKey(IntPtr window, Keys key, bool up)
        {
            SetForegroundWindow(window);
            PressKey(key, up);
        }

        /// <summary>
        /// Set The Blink Speed in Milisecond
        /// </summary>
        /// <param name="Speed">Speed in Milisecond to Sleep</param>
        public static void SetBlinkSpeed(BlinkSpeed Speed)
        {
            BLINK_SPEED = Speed;
        }

        /// <summary>
        /// Get Blink Speed in Milisecond
        /// </summary>
        /// <returns>Speed in Milisecond to Sleep</returns>
        public static int GetBlinkSpeed()
        {
            return (int)BLINK_SPEED;
        }

        public static void DrawBorder(Rectangle rectCapture)
        {
            if (Properties.Settings.Default.UseGDIWhenDrawBorder)
            {
                IntPtr desktop = GetDC(IntPtr.Zero);
                IntPtr hPen = CreatePen(PenStyle.PS_INSIDEFRAME, 3, (uint)0x0000FF);
                int nMode = SetROP2(desktop, 10);
                IntPtr hPenOld = SelectObject(desktop, hPen);

                //::GetWindowRect(hwndCapture,&rectCapture);

                POINT[] pt = new POINT[5];

                pt[0] = new POINT(rectCapture.Left, rectCapture.Top);
                pt[1] = new POINT(rectCapture.Right, rectCapture.Top);
                pt[2] = new POINT(rectCapture.Right, rectCapture.Bottom);
                pt[3] = new POINT(rectCapture.Left, rectCapture.Bottom);
                pt[4] = new POINT(rectCapture.Left, rectCapture.Top);
                Polyline(desktop, pt, 5);

                //System.Threading.Thread.Sleep(500);

                //Polyline(desktop, pt, 5);
                SelectObject(desktop, hPenOld);
                ReleaseDC(desktop);
            }
            else
            {
                System.Windows.Forms.ControlPaint.DrawReversibleFrame(rectCapture, Color.Crimson, System.Windows.Forms.FrameStyle.Thick);
            }
        }

        private static Rectangle _Bounds = Rectangle.Empty;
        /// <summary>
        /// Start Blink border for any screen rect by draw Reversable on desktop graphics (NOT_XOR_PEN or INVERT)
        /// </summary>
        /// <param name="Bounds">Rectangle in Screen Coordinator</param>
        public static void BlinkBorderBefore(Rectangle Bounds)
        {
            if (_Bounds != Rectangle.Empty) MessageBox.Show("You forget to call BlinkBorderAfter somewhere to Reverse Last Border", "WARNING : Forget Blink After !");
            _Bounds = Bounds;
            DienLib.WinAPI.DrawBorder(_Bounds);
            System.Threading.Thread.Sleep((int)BLINK_SPEED);
        }
        /// <summary>
        /// Stop Blink border for any screen rect by draw Reversable again on desktop graphics (NOT_XOR_PEN or INVERT)
        /// </summary>
        public static void BlinkBorderAfter()
        {
            if (_Bounds == Rectangle.Empty) MessageBox.Show("You should call BlinkBorderBefore first to Draw Reversable Border", "WARNING : Forget Blink Before !");
            System.Threading.Thread.Sleep((int)BLINK_SPEED);
            DienLib.WinAPI.DrawBorder(_Bounds);

            //DienLib.WinAPI.DrawBorder(_Bounds);
            //System.Threading.Thread.Sleep((int)BLINK_SPEED);
            //DienLib.WinAPI.DrawBorder(_Bounds);
            _Bounds = Rectangle.Empty;
        }

        /// <summary>
        /// Stop Blink border for any screen rect by draw Reversable again on desktop graphics (NOT_XOR_PEN or INVERT) & then refresh Top Form to eraser any artifact (if move form while drawing)
        /// </summary>
        /// <param name="Ctrl">TopLevelControl of this Control will be used to refresh at last (erase all Border if Moving while drawing)</param>
        public static void BlinkBorderAfter(Control Ctrl)
        {
            if (_Bounds == Rectangle.Empty) MessageBox.Show("You should call BlinkBorderBefore first to Draw Reversable Border", "WARNING : Forget Blink Before !");
            //DienLib.WinAPI.DrawBorder(_Bounds);
            System.Threading.Thread.Sleep((int)BLINK_SPEED);
            DienLib.WinAPI.DrawBorder(_Bounds);
            //System.Threading.Thread.Sleep((int)BLINK_SPEED);
            if (Ctrl.InvokeRequired) Ctrl.Invoke((MethodInvoker)delegate { Ctrl.TopLevelControl.Refresh(); });
            else Ctrl.TopLevelControl.Refresh(); ;
            _Bounds = Rectangle.Empty;
        }

        public static bool WriteNotePad(string text)
        {
            Process notepad;
            try
            {
                Process[] notepads = Process.GetProcessesByName("notepad");
                if (notepads.Length == 0)
                {  // No notepad open
                    notepad = Process.Start("notepad"); // Start Notepad
                    System.Threading.Thread.Sleep(1000); // Wait for NotePad started or will miss the code
                }
                else
                {  // Already have notepad open
                    if (!notepads[0].MainWindowTitle.Contains("Untitled"))
                    { // No Untitled Notepad Open
                        notepad = Process.Start("notepad");
                        System.Threading.Thread.Sleep(1000); // Wait for NotePad started or will miss the code
                    }
                    else
                    {
                        notepad = notepads[0];
                    }
                }
                IntPtr child = FindWindowEx(notepad.MainWindowHandle, new IntPtr(0), "Edit", null);
                SendMessage(child, 0x000C, 0, text);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return true;
        }

        public static void DrawRevFrame(IntPtr hWnd)
        {
            if (hWnd == IntPtr.Zero)
                return;

            IntPtr hdc = GetWindowDC(hWnd);
            RECT rect;
            GetWindowRect(hWnd, out rect);
            OffsetRect(ref rect, -rect.Left, -rect.Top);

            const int frameWidth = 3;
            //const int clearance = 5;

            PatBlt(hdc, rect.Left, rect.Top, rect.Right - rect.Left, frameWidth, DSTINVERT); // hdc tuc chi ve trong khu vuc gioi han cua control thoi ???? is that right ?
            PatBlt(hdc, rect.Left, rect.Bottom - frameWidth, frameWidth, -(rect.Bottom - rect.Top - 2 * frameWidth), DSTINVERT);
            PatBlt(hdc, rect.Right - frameWidth, rect.Top + frameWidth, frameWidth, rect.Bottom - rect.Top - 2 * frameWidth, DSTINVERT);
            PatBlt(hdc, rect.Right, rect.Bottom - frameWidth, -(rect.Right - rect.Left), frameWidth, DSTINVERT);
        }

        private const int MAXCOUNT_WIN_TITLE = 64;
        private const int MAXCOUNT_CLASS_NAME = 32;
        /// <summary>
        /// Find all Windows in the provided Process match the windowName. Futher implement no need Proc. List all Open Proc & Search all the Thread.
        /// </summary>
        /// <param name="proc">Process to find Window</param>
        /// <param name="windowName">Title of Window</param>
        /// <param name="culture">Exact Match or just Partial Match with or without Case-Sensitive</param>
        /// <returns>List of IntPtr of Windows Found</returns>
        public static List<IntPtr> FindWindowLike(Process proc, string windowName, FindCulture culture)
        {
            if (proc == null) throw new ArgumentNullException("Null Process Pass to Method");
            if (windowName == null) throw new ArgumentNullException("Null windowName Pass to Method");
            if (windowName == string.Empty) throw new Exception("Empty windowName pass to Method");

            var handles = new List<IntPtr>();
            foreach (ProcessThread thread in proc.Threads)
                //EnumThreadWindows(thread.Id, new EnumThreadDelegate(WinAPI.EnumThreadCallback), IntPtr.Zero); // Co the truyen List vao thong qua GCHandle.Alloc & phục hồi GCHandle.FromIntPtr in Callback
                EnumThreadWindows(thread.Id, (hWnd, lParam) => // Lamda Delegate
                {
                    StringBuilder sbWinTitle = new StringBuilder(MAXCOUNT_WIN_TITLE);
                    GetWindowText(hWnd, sbWinTitle, MAXCOUNT_WIN_TITLE);
                    if (sbWinTitle.Length > 0)
                    {
                        switch (culture)
                        {
                            case FindCulture.EXACT_MATCH: if (sbWinTitle.ToString().Trim().Equals(windowName.Trim())) handles.Add(hWnd); break;
                            case FindCulture.EXACT_MATCH_IGNORE_CASE: if (sbWinTitle.ToString().Trim().Equals(windowName.Trim(), StringComparison.CurrentCultureIgnoreCase)) handles.Add(hWnd); break;
                            case FindCulture.PARTIAL_MATCH: if (sbWinTitle.ToString().Contains(windowName.Trim())) handles.Add(hWnd); break;
                            case FindCulture.PARTIAL_MATCH_IGNORE_CASE: if (sbWinTitle.ToString().ToLower().Contains(windowName.Trim().ToLower())) handles.Add(hWnd); break;
                        }
                    }
                    return true;
                }, IntPtr.Zero);

            return handles;
        }

        /// <summary>
        /// Find all Windows in the provided Process match any of the windowNames Array
        /// </summary>
        /// <param name="proc">Process to find Windows</param>
        /// <param name="windowNames">WindowName Array : Contain Possible Name</param>
        /// <param name="culture">Exact Match or just Partial Match with or without Case-Sensitive</param>
        /// <returns>List of IntPtr of Windows Found</returns>
        public static List<IntPtr> FindWindowLike(Process proc, string[] windowNames, FindCulture culture)
        {
            if (proc == null) throw new ArgumentNullException("Null Process Pass to Method");
            if (windowNames == null) throw new ArgumentNullException("Null windowNames Pass to Method");
            if (windowNames.Length == 0) throw new Exception("Empty windowNames Array");

            var handles = new List<IntPtr>();
            foreach (string st in windowNames)
                if (st == string.Empty) throw new Exception("Empty windowName pass to Method");
                else handles.AddRange(FindWindowLike(proc, st, culture));

            return handles;
        }

        private static bool EnumThreadCallback(IntPtr hWnd, IntPtr lParam)
        {
            // windowHandle = (IntPtr)hwnd;
            //listBoxHandle = (IntPtr)lParam;
            // getting an instance of listbox from its handle.
            //ListBox lb = (ListBox)ListBox.FromHandle(listBoxHandle);
            StringBuilder sbWinTitle = new StringBuilder(MAXCOUNT_WIN_TITLE);
            //StringBuilder sbc = new StringBuilder(256);
            //GetClassName(hwnd, sbc, sbc.Capacity);
            GetWindowText(hWnd, sbWinTitle, MAXCOUNT_WIN_TITLE);
            if (sbWinTitle.Length > 0)
            { // Found WinTitle

            }

            /*if (sbc.ToString().Equals("IEFrame"))
                {f
                    myAl.Add(windowHandle);
                    i++;
                    lb.Items.Add(xMsg);
                }
            }*/
            return true;
        }

        #endregion

    }
}
